package cn.edu.csust.cvs.management.service.impl;

import cn.edu.csust.cvs.management.common.ApiPageResult;
import cn.edu.csust.cvs.management.common.ApiResponse;
import cn.edu.csust.cvs.management.controller.request.RecordDeleteRequest;
import cn.edu.csust.cvs.management.controller.request.RecordPageQueryRequest;
import cn.edu.csust.cvs.management.repository.RecordRepository;
import cn.edu.csust.cvs.management.repository.entity.RecordEntity;
import cn.edu.csust.cvs.management.service.RecordService;
import cn.edu.csust.cvs.management.support.FileUploadSupport;
import cn.edu.csust.cvs.management.utils.VideoParseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class RecordServiceImpl implements RecordService {

    @Value("${local.path.audio}")
    String audioPath;

    @Autowired
    FileUploadSupport fileUploadSupport;

    @Autowired
    RecordRepository recordRepository;

    private static final Integer ADMIN = 1;

    @Override
    public ApiResponse upload(MultipartFile multipartFile) {
        String fileName = multipartFile.getOriginalFilename();
        String filePath = audioPath + fileName;
        File file = new File(filePath);
        try {
            if (file.exists()) {
                org.apache.commons.io.FileUtils.forceDelete(file);
            }
        }catch (IOException e) {
            log.debug("file force delete failed.");
        }
        try {
            multipartFile.transferTo(file);
        }catch (IOException e) {
            e.printStackTrace();
            log.debug("multipartFile transfer to file failed.");
        }
        String fileUrl = fileUploadSupport.uploadAudio(fileName,file.getPath());
        long duration = VideoParseUtils.getAudioDuration(file.getAbsolutePath());
        long size = file.length();
        RecordEntity entity = new RecordEntity();
        entity.setCreateTime(LocalDateTime.now());
        entity.setDuration(duration);
        entity.setSize(size);
        entity.setFileUrl(fileUrl);
        entity.setFilePath(filePath);
        entity.setCreateBy(ADMIN);
        entity.setName(fileName);
        this.recordRepository.save(entity);

        return ApiResponse.ok();
    }

    @Override
    public ApiPageResult<List<RecordEntity>> pageQuery(RecordPageQueryRequest request) {
        //规格定义
        Specification<RecordEntity> specification = new Specification<RecordEntity>() {
            /**
             * 构造断言
             * @param root 实体对象引用
             * @param query 规则查询对象
             * @param cb 规则构建对象
             * @return 断言
             */
            @Override
            public Predicate toPredicate(Root<RecordEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                if(StringUtils.isNotBlank(request.getName())){
                    Predicate likeName = cb.like(root.get("name").as(String.class),"%"+request.getName()+"%");
                    predicates.add(likeName);
                }
                return cb.and(predicates.toArray(new Predicate[0]));
            }
        };
        //分页信息
        Sort sort;
        if (StringUtils.isNotBlank(request.getOrder())){
            sort = Sort.by(Sort.Direction.DESC,request.getOrder());
        }else{
            sort = Sort.by(Sort.Direction.DESC,"id");
        }
        Pageable pageable = PageRequest.of(request.getPageNo()-1,request.getPageSize(),sort);
        //查询
        Page<RecordEntity> page = this.recordRepository.findAll(specification,pageable);
        return ApiPageResult.ok(page.getTotalPages(),page.getTotalElements(),request.getPageSize(), (long) request.getPageNo(),page.getContent());
    }

    @Override
    public ApiResponse delete(RecordDeleteRequest request) {
        List<RecordEntity> entities = new ArrayList<>(20);
        request.getIds().stream().forEach(x->{
            RecordEntity entity = new RecordEntity();
            entity.setId(x);
            entities.add(entity);
        });
        this.recordRepository.deleteInBatch(entities);
        return ApiResponse.ok();
    }

    @Override
    public ApiResponse rename(Integer id, String name) {
        Optional<RecordEntity>  optional = this.recordRepository.findById(id);
        RecordEntity recordEntity = optional.get();
        recordEntity.setName(name);
        this.recordRepository.save(recordEntity);
        return ApiResponse.ok();
    }
}
